package com.dev;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.view.WindowManager;
import android.view.Gravity;
public class TabBar extends LinearLayout {
	public static LinearLayout.LayoutParams tablp;
	public final static int clickLimit=350;
	public final static int doubleClickInterval=300;
	MainActivity ma;
    Shadow sh;
    public TabBar(MainActivity ma) {
		super(ma);
		setOrientation(HORIZONTAL);
		setWillNotDraw(false);
		tablp = new LayoutParams((int)(90 * ma.dp), -1);
        sh=new Shadow(ma);
	}
	View targetView;
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev){
		switch(ev.getAction()){
			case MotionEvent.ACTION_DOWN:
				for(int i=0;true;i++){
					if(i<getChildCount()){
						View child=getChildAt(i);
						if(child.getVisibility()==View.VISIBLE||child.getVisibility()==View.INVISIBLE){
							int x=(int)ev.getX();
							int y=(int)ev.getY();
							if(x>=child.getLeft()&&x<=child.getRight()&&y>=child.getTop()&&y<=child.getBottom()){
								targetView=child;
								ev.setLocation(ev.getX()-targetView.getLeft(),ev.getY()-targetView.getTop());
								targetView.dispatchTouchEvent(ev);
								break;
							}
						}
					}else{
						targetView=null;
						return true;
					}
				}
				break;
			case MotionEvent.ACTION_MOVE:
				if(targetView!=null){
					ev.setLocation(ev.getX()-targetView.getLeft(),ev.getY()-targetView.getTop());
					targetView.dispatchTouchEvent(ev);
				}
				break;
			case MotionEvent.ACTION_UP:
				if(targetView!=null){
					ev.setLocation(ev.getX()-targetView.getLeft(),ev.getY()-targetView.getTop());
					targetView.dispatchTouchEvent(ev);
				}
				break;
			case MotionEvent.ACTION_CANCEL:
				if(targetView!=null){
					ev.setLocation(ev.getX()-targetView.getLeft(),ev.getY()-targetView.getTop());
					targetView.dispatchTouchEvent(ev);
				}
		}
		return true;
	}
	static final class Shadow extends View{
        WindowManager.LayoutParams wlp=new WindowManager.LayoutParams();
        Tab target;
        Shadow(MainActivity ma){
            super(ma);
            wlp.gravity=Gravity.LEFT|Gravity.TOP;
            wlp.flags=wlp.FLAG_LAYOUT_IN_SCREEN;
        }
        @Override
        protected void onDraw(Canvas canvas) {
            if(target==null){
                canvas.drawColor(0xff777777);
            }else
            target.drawShadow(canvas);
        }
        
    }
	public static abstract class TypicTab extends TextView implements Tab {
		MainActivity ma;
		Rect layoutSaved=new Rect();
		public Paint textPaint=new Paint();
		Paint p2=new Paint();
		Paint p1=new Paint();
		OnClickListener ocl;
		OnLongClickListener olcl;
		public boolean tabUnderline;
		public boolean textUnderline;
		public boolean dontDrawContent=false;
		public int textColor;
		volatile boolean touchMoved,longClicked;
		volatile boolean willDoubleClick,onDoubleClicked;
		Point touchDownRaw=new Point();
		int touch_moveFarthest;
		long doubleClickTime;
		long touchDownTime;
		WaitLongClick wlc;
		boolean onSlip;
		boolean needRemember=true;
		public TypicTab(MainActivity ma) {
			super(ma);
			this.ma = ma;
			setTypeface(Typeface.MONOSPACE);
			setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
		}
		@Override
		public void letUnderline(boolean b) {
			tabUnderline=b;
			invalidate();
		}
		public void setOnClickListener(View.OnClickListener l) {
			ocl=l;
		}
		public void setOnLongClickListener(View.OnLongClickListener l) {
			olcl=l;
		}
		@Override
		public void setTextColor(int color) {
			super.setTextColor(color);
			textColor=color;
		}
		public void drawShadow(Canvas c){
			c.drawColor(0xff888888);
			drawContent(c);
		}
		void drawContent(Canvas c){
			String name=getText().toString();
			if(name.isEmpty()){
				name="Untitled";
			}
			float[] ws=new float[name.length()];
			int widths=textPaint.getTextWidths(name,ws);
			int i;
			float width=0;
			int vw=getWidth();
			int vh=getHeight();
			for(i=widths-1;i>=0;i--){
				width+=ws[i];
				if(width>vw){
					break;
				}
			}
			int ii=vh/5;  
			String truncated=name.substring(i+1);
			int textx=(vw-(int)textPaint.measureText(truncated))/2;
			Paint.FontMetricsInt pfi=textPaint.getFontMetricsInt();
			int texty=(pfi.descent-pfi.ascent)/2+vh/2-ii/2;
			c.drawText(truncated,textx,texty,textPaint);
			if(textUnderline){
				textPaint.setStrokeWidth(2);
				int ly=texty+pfi.descent;
				c.drawLine(textx,ly,textx+textPaint.measureText(truncated),ly,textPaint);
			}
			if(tabUnderline){
				c.drawRect(0,getHeight()-5,getWidth(),getHeight(),p2);
			}
		}
		@Override
		public boolean isNeedRemember() {
			return needRemember;
		}
		@Override
		protected void onDraw(Canvas canvas){
			textPaint.setTextSize(getTextSize());
			textPaint.setColor(textColor);
			textPaint.setTypeface(getTypeface());
			int vw=getWidth();
			int vh=getHeight();
			int ii=vh/5;  
			canvas.drawRect(vw-3,ii,vw,vh-ii,p1);
			if(!dontDrawContent){
				drawContent(canvas);
			}
		}
		@Override
		public boolean onTouchEvent(MotionEvent event){
			int rx=(int)event.getRawX();//Toast.makeText(ma,"23333",0).show();
			int ry=(int)event.getRawY();
			int slip=ry-touchDownRaw.y;
			int drag=rx-touchDownRaw.x;
            TabBar.Shadow sh=ma.gui.tabs.sh;
			switch(event.getAction()){
				case MotionEvent.ACTION_DOWN:
                    getGlobalVisibleRect(layoutSaved);
					onSlip=false;
					touchMoved=false;
					longClicked=false;
					touchDownRaw.x=rx;
					touchDownRaw.y=ry;
					touch_moveFarthest=0;
					touchDownTime=System.currentTimeMillis();
					ma.gui.hsv.requestDisallowInterceptTouchEvent(true);
					if(willDoubleClick){
						int gap=(int)(System.currentTimeMillis()-doubleClickTime);
						doubleClickTime=System.currentTimeMillis();
						if(gap<=TabBar.doubleClickInterval){
							onDoubleClicked=true;
							dontDrawContent=true;
                            sh.wlp.x=layoutSaved.left;
                            sh.wlp.y=layoutSaved.top;
                            sh.wlp.width=layoutSaved.width();
                            sh.wlp.height=layoutSaved.height();
                            sh.target=this;
                            ma.wm.addView(sh,sh.wlp);
							invalidate();
						}else{
							onDoubleClicked=false;
							if(wlc==null){
								wlc=new WaitLongClick();
								wlc.start();
							}else{
								wlc.interrupt();
								wlc=new WaitLongClick();
								wlc.start();
							}
						}
					}else{
						willDoubleClick=true;
						doubleClickTime=System.currentTimeMillis();
						if(wlc==null){
							wlc=new WaitLongClick();
							wlc.start();
						}else{
							wlc.interrupt();
							wlc=new WaitLongClick();
							wlc.start();
						}
					}
					break;
				case MotionEvent.ACTION_MOVE:
					if(onDoubleClicked){
						int shadowx=layoutSaved.left+drag;
                        int shadowy=layoutSaved.top+slip;
						sh.wlp.x=shadowx;
                        invalidate();
                        if(shadowy<=layoutSaved.top){
                            sh.wlp.y=layoutSaved.top;
                            dontDrawContent=true;
                        }else if(shadowy<layoutSaved.bottom){
                            sh.wlp.y=shadowy;
                            dontDrawContent=true;
                        }else{
                            sh.wlp.y=layoutSaved.bottom;
                            int cx=shadowx+layoutSaved.width()/2;
                            int cen=ma.wp/2;
                            if(cx<cen){
                                sh.wlp.x=0;
                            }else{
                                sh.wlp.x=ma.wp-sh.wlp.width;
                            }
                            ma.wm.updateViewLayout(sh,sh.wlp);
                            ma.gui.hsv.requestDisallowInterceptTouchEvent(true);
                            dontDrawContent=false;
                            invalidate();
                            
                            return true;
                        }
                        int cx=shadowx+layoutSaved.width()/2;
                        ma.wm.updateViewLayout(sh,sh.wlp);
						ma.gui.hsv.requestDisallowInterceptTouchEvent(true);
						outmost:
						for(int i=0,count=ma.gui.tabs.getChildCount();true;i++){
							if(i<count){
								View child=ma.gui.tabs.getChildAt(i);
								if(child.getVisibility()!=View.GONE){
									if(cx>=child.getLeft()&&cx<=child.getRight()){
										if(child==this){
											ma.gui.tabs.invalidate();
											//ma.gui.requestLayout();
											break;
										}else{
											ma.gui.tabs.removeView(this);
											ma.gui.tabs.addView(this,i);
											//ma.gui.tabs.requestLayout();
											break;
										}
									}else if(child==this){
										for(i++;true;i++){
											if(i<count){
												child=ma.gui.tabs.getChildAt(i);
												if(cx>=child.getLeft()&&cx<=child.getRight()){
													ma.gui.tabs.removeView(this);
													ma.gui.tabs.addView(this,i);
													//ma.gui.tabs.requestLayout();
													break outmost;
												}
											}else{
												ma.gui.tabs.invalidate();
												break outmost;
											}
										}
									}
								}
							}else{
								ma.gui.tabs.invalidate();
								break;
							}
						}
					}else{
						if(touchMoved){
							if(onSlip){
								ma.gui.hsv.requestDisallowInterceptTouchEvent(true);
								if(slip>0){
									setScrollY(-slip);
								}else setScrollY(0);
							}else{
								ma.gui.hsv.requestDisallowInterceptTouchEvent(false);
								return false;
							}
						}else{
							getParent().getParent().requestDisallowInterceptTouchEvent(true);
							int slip_abs=Math.abs(slip);
							int drag_abs=Math.abs(drag);
							if(slip_abs>8||drag_abs>8){
								touchMoved=true;
								if(wlc!=null){
									wlc.interrupt();
								}
								if(slip_abs>drag_abs&&!onDoubleClicked){
									onSlip=true;
									if(slip>0){
										setScrollY(-slip);
									}else setScrollY(0);
								}
							}
						}
					}
					break;
				case MotionEvent.ACTION_UP:
					if(wlc!=null)	{
						wlc.interrupt();
						wlc=null;
					}
                    if(sh.isAttachedToWindow())ma.wm.removeView(sh);
					if(onDoubleClicked){
						dontDrawContent=false;
						willDoubleClick=false;
						invalidate();
                        int shadowx=layoutSaved.left+drag;
                        int shadowy=layoutSaved.top+slip;
                        if(shadowy>=layoutSaved.bottom){
                            ma.gui.tabs.removeView(this);
                            int cx=shadowx+layoutSaved.width()/2;
                            int cen=ma.wp/2;
                            if(cx<cen){
                                sh.wlp.x=0;
                                ma.gui.tabs.addView(this,0);
                            }else{
                                sh.wlp.x=ma.wp-sh.wlp.width;
                                ma.gui.tabs.addView(this,ma.gui.tabs.getChildCount());
                            }
                        }
						ma.gui.saveAllTab();
					}else if(onSlip){
						slip=ry-touchDownRaw.y;
						setScrollY(0);
						if(slip>getHeight()){
							ma.gui.onTabSlipped(this);
						}
					}else if(ocl!=null){
						if(!touchMoved){
							if(!longClicked){
								ocl.onClick(this);
							}
						}
					}
					onDoubleClicked=false;
					break;
				case MotionEvent.ACTION_CANCEL:
					if(wlc!=null){
						wlc.interrupt();
						wlc=null;
					}
                    if(sh.isAttachedToWindow())ma.wm.removeView(sh);
					if(onDoubleClicked){
						dontDrawContent=false;
						invalidate();
					}else if(onSlip){
						setScrollY(0);
					}
					willDoubleClick=false;
					onDoubleClicked=false;
					break;
			}
			return true;
		}
		class WaitLongClick extends Thread {
			@Override
			public void run() {
				super.run();
				try{
					sleep(TabBar.clickLimit);
					longClicked=true;
					if(olcl!=null){
						post(new Runnable(){
								public void run(){
									olcl.onLongClick(TypicTab.this);
								}
							});
					}
				}catch(InterruptedException e){
					//log.alert(e.toString());
				}
			}
		}
	}
	static interface Tab {
		void letUnderline(boolean b);
		void drawShadow(Canvas c);
		boolean isNeedRemember();
	}
}
